<?php
/**
 * Created by PhpStorm.
 * User: liuyu
 * Date: 2018/6/12
 * Time: 11:46
 */

namespace App\Models\CacheModel;

use app\aliyun\controller\AliyunFilterWord;
use app\astro\controller\Index as AstroIndex;
use App\Models\CacheModel\Recode as RecodeCacheModel;
use app\common\lib\astrolog\Astrolog;
use app\common\lib\cache\CacheTools;
use App\Exceptions\ApiException;
use app\common\lib\Util;
use App\Models\Api\BaseCache;
use App\Models\Api\User;
use Exception;
use Cache;
use Db;
use Log;
use AstroTool\Cache\CacheManage;

/**
 * 用户档案数据操作类
 * Class Recode
 * @package App\Models\Api
 */
class Recode extends BaseCache
{
    protected $table = 'recode';
    protected $cacheModel = 'recode.recode';
    protected $field = true;
    protected $userBirthCacheKey = 'recode.birth_list';

    /**
     * 获取用户一个月内所有档案的生日信息
     * @param array $user 用户信息
     * @param string $date 2020-09 或 2020-07-18
     * @param float $timezone 时区
     * @return array|bool|mixed|string
     * @throws Exception
     */
    public function userBirthMonthList($user, $date, $timezone)
    {
        $timezone = (float)($timezone ?? 8);
        $uid = $user['id'] ?? 0;
        if ($uid)
        {
            $key = $uid . '-' . date('n', strtotime($date)) . ':' . $timezone;
            //获取用户所有的档案
            $recodeData = $this->getRecodeLists($uid);
            $data = CacheManage::getInstance()->setCacheConfig($this->userBirthCacheKey, $key)
                ->getDataAndSet(function () use ($timezone, $user, $date, $recodeData)
                {
                    $self_recode = [];
                    $else_recode = [];
                    foreach ($recodeData as $recodeDatum)
                    {
                        $birth = $this->checkRecodeBirth($user, $recodeDatum, date('Y-m', strtotime($date)), $timezone);
                        if ($birth)
                        {
                            //自己的档案顺序在前
                            if ($birth['type'] == 1)
                            {
                                $self_recode[] = $birth;
                            } else
                            {
                                $else_recode[] = $birth;
                            }
                        }
                    }
                    $data = array_merge($self_recode, $else_recode);
                    return json_encode($data, true);
                });

            if (is_string($data))
            {
                $data = json_decode($data, true);
            }

        } else
        {
            $data = [];
        }
        return $data;
    }

    /**
     * 获取用户一天内所有档案的生日信息
     * @param $user
     * @param $date 2020-07-18
     * @param int $timezone
     * @return array
     * @throws Exception
     */
    public function userBirthDayList($user, string $date, int $timezone = 8)
    {
        [$year, $month, $day] = explode('-', $date);
        $nowTime = (int)((int)$month . (int)$day);
        $data = $this->userBirthMonthList($user, $date, $timezone);
        $res = [];
        foreach ($data as $datum)
        {
            $recodeTime = (int)((int)$datum['month'] . (int)$datum['day']);
            if ($recodeTime === $nowTime)
            {
                $res[] = $datum;
            }
        }
        return $res;
    }

    /**
     * 检查档案生日
     * @param array $user 用户信息
     * @param array $recode 档案信息
     * @param $date 2020-09 或 2020-07-18
     * @param float $timezone 时区
     * @return array|array[]
     * @throws Exception
     */
    public function checkRecodeBirth($user, $recode, $date, $timezone = 8)
    {
        $arr = [];
        //$isYoung = $user ? $user['young_model'] : false; // 是否是青少年模式
        $isYoung ='';
        $astroCalendarNeedAuth = $isYoung ? 3 : 0;
        $dateArr = explode('-', $date);
        [$recode_year, $recode_month, $recode_day] = [$recode['year'], $recode['month'], $recode['day']];
//        //获取用户当前时区下的出生时间
//        $timezone = (float)($timezone ?? 8);
//        $recode_time = gmdateModify('Y-m-d', strtotimeModify('U', $recode['year'] . '-' . $recode['month'] . '-' . $recode['day']), $recode['timezone'], $timezone);
//        [$recode_year, $recode_month, $recode_day] = explode('-', $recode_time);
        $is_birth = false;

        if (count($dateArr) > 2)
        {
            [$year, $month, $day] = $dateArr;
            //判断是否今日生日
            if ($recode_month == $month && $recode_day == $day)
            {
                $is_birth = true;
            }
        } else
        {
            [$year, $month] = $dateArr;
            //判断是否本月生日
            if ($recode_month == $month)
            {
                $is_birth = true;
            }
        }
        //判断是否生日
        if ($is_birth === true)
        {
            if ($recode['isself'])
            {
                $type = 1;
                $target = 'link';
                $link = '/web/birthday/boon?need_auth=' . $astroCalendarNeedAuth . '&umeng_event_name=common_target_link&umeng_event_label=' . urlencode('生日权益页面-日历页面-领取权益');
                $btn_text = '领取权益';
                $birth = '祝可爱的你生日快乐！';
            } else
            {
                $type = 2;
                $target = 'link';
                $link = '/web/birthday/sendwish?rid=' . $recode['id'] . '&need_auth=' . $astroCalendarNeedAuth . '&umeng_event_name=common_target_link&umeng_event_label=' . urlencode('祝福好友页面-日历页面-祝福好友');
                $btn_text = '祝福好友';
                //            名称长度最长为4
                $nameLen = mb_strlen($recode['name']);
                if ($nameLen > 4)
                {
                    $name = mb_substr($recode['name'], 0, 4);
                } else
                {
                    $name = $recode['name'];
                }
                $birth = '今天是' . $name . '的生日！';
            }
            $arr = [
                'type' => $type,
                'name' => $recode['name'],
                'avatar' => $recode['avatar'],
                'text' => $birth,
                'target' => $target,
                'link' => $link,
                'btn_text' => $btn_text,
                'year' => $recode_year,
                'month' => $recode_month,
                'day' => $recode_day
            ];
        }
        return $arr;
    }

    public function cat()
    {
        return $this->belongsToMany('Cat', 'wechat_backup_07_18_14_43_00.app_recode_cat', 'cid', 'rid');
    }

    /**
     * 添加档案
     * @param $uid
     * @param $map
     * @return int|string
     * @throws Exception
     */
    public function SaveData($uid, $map)
    {
        //生成档案or_day
        //1.准币支付，免费支付，三方支付,初始化or_day为档案day
        //更新or_day
        //1.采纳生时矫正时，更新or_day为当前档案day

        $timezone = (float)(request()->header()['timezone'] ?? 8);
        try
        {
            $map['or_day'] = 0;//新增档案or_day重置0
            $id = $this->insertGetId($map);
        }
        catch (Exception $e)
        {
            $this->error = '添加失败';
            return false;
        }
//        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(0)->rmCache('list');
        if (isset($map['isself']) && $map['isself'] == 1)
        {
            $this->listDataAdd($uid, [$id => $id], 1);
            //删除用户缓存
            (new User())->updateUserinfo(['id' => $uid], ['has_self_recode' => 1]);
        } else
        {
            $this->listDataAdd($uid, [$id => $id], 0);
        }
        //清除用户档案生日信息缓存
        $key1 = $uid . '-' . (int)$map['month'] . ':' . $timezone;
        CacheManage::getInstance()->setCacheConfig($this->userBirthCacheKey, $key1)->rmCache();//清除更新月日的生日缓存
        //清除用户档案生日信息缓存
        $key2 = $uid . '-' . (int)$map['month'] . '-' . ':' . (float)($map['timezone'] ?? 8);
        CacheManage::getInstance()->setCacheConfig($this->userBirthCacheKey, $key2)->rmCache();
        return $id;
    }

    /**
     * 更新档案
     * @param $uid
     * @param $rid
     * @param array $data
     * @param int $alter_or_day
     * @return bool
     * @throws Exception
     */
    public function UpdateData($uid, $rid, $data = [], $alter_or_day = 0)
    {
        $timezone = (float)(request()->header()['timezone'] ?? 8);
        $recode = $this->getInfoById($rid, ['year', 'month', 'day', 'timezone', 'or_day']);
        if ($recode)
        {
            try
            {
                if ($alter_or_day)
                {
                    $data['or_day'] = $recode['day'];
                }
                if ($data)
                {
                    $this->allowField(true)->isUpdate(true)->save($data, ['uid' => $uid, 'id' => $rid]);
                    // 记录用户更新档案的时间
                    Db::table('recode_info')->where('rid', $rid)->update(['last_time' => time()]);
                }
                //删除档案详情缓存
                CacheManage::getInstance()->setCacheConfig($this->cacheModel, $rid)->rmCache();
                if (isset($data['isself']) && $data['isself'] == 1)
                {
                    Cache::forget('userinfo:' . $uid); // 删除用户缓存
                    CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(1)->rmCache('list');
                }
            }
            catch (Exception $e)
            {
                $this->error = '更新失败';
                return false;
            }
            //当用户更新档案时间，则清除
            if (isset($data['year'], $data['month'], $data['day'], $data['timezone']))
            {
                //清除用户档案生日信息缓存
                $key1 = $uid . '-' . (int)$data['month'] . ':' . $timezone;
                CacheManage::getInstance()->setCacheConfig($this->userBirthCacheKey, $key1)->rmCache();//清除更新月日的生日缓存
            }
            $key2 = $uid . '-' . (int)$recode['month'] . ':' . (float)$recode['timezone'];
            CacheManage::getInstance()->setCacheConfig($this->userBirthCacheKey, $key2)->rmCache();//清除旧档案月日的生日缓存
        }
        return true;
    }

    /**
     * 删除档案
     * @param $uid
     * @param $map
     * @return bool
     * @throws Exception
     */
    public function DelData($uid, $rid, $map, $isself = 0)
    {
        $timezone = (float)(request()->header()['timezone'] ?? 8);
        $recode = $this->getInfoById($rid, ['year', 'month', 'day', 'timezone']);
        try
        {
            $this->where(['id' => $rid])->update($map);
        }
        catch (Exception $e)
        {
            $this->error = '删除失败';
            return false;
        }
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(0)->rmCache('list');
        if ($isself == 1)
        {
            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(1)->rmCache('list');
        }
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $rid)->rmCache();
        //当用户删除档案时，则清除
        if (isset($recode['year'], $recode['month'], $recode['day'], $recode['timezone']))
        {
            //清除用户档案生日信息缓存
            $key1 = $uid . '-' . (int)$recode['month'] . ':' . $timezone;
            CacheManage::getInstance()->setCacheConfig($this->userBirthCacheKey, $key1)->rmCache();//清除更新月日的生日缓存
            $key2 = $uid . '-' . (int)$recode['month'] . ':' . (float)$recode['timezone'];
            CacheManage::getInstance()->setCacheConfig($this->userBirthCacheKey, $key2)->rmCache();//清除旧档案月日的生日缓存
        }
        return true;
    }

    /**
     * 获取当前用户的档案列表或用户自己的档案信息
     * @param int $uid
     * @param int $isself 0=》获取用户全部档案 1=》获取用户自己的档案
     * @return array
     * @throws Exception
     */
    public function getRecodeLists($uid, $isself = 0)
    {
        $field = ['id', 'name', 'type', 'year', 'month', 'day', 'hour', 'minute', 'timezone', 'birth_country', 'birth_province', 'birth_city', 'live_country', 'live_province', 'live_city', 'comments', 'isself', 'long_deg', 'long_min', 'ew', 'lat_deg', 'lat_min', 'ns', 'avatar', 'is_summer', 'uid', 'aid', 'sun', 'moon', 'merc', 'venu', 'mars', 'jupi', 'satu', 'non', 'lili', 'juno', 'asc', 'mc', 'or_day', 'status', 'from', 'is_read'];
        $rids = CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)
            ->setListKeyType($isself)
            ->ZsGetIocData('list', function () use ($uid, $isself)
            {
                if ($isself)//获取用户自己的档案
                {
                    return $this->getSelfRecodeFromDms($uid);
                }
                return $this->getUserAllRecodeIdFromDms($uid);
            });

        $recode = $this->batchGetInfoByIds($rids, $field);
        array_multisort(array_column($recode, 'id'), SORT_NUMERIC, SORT_DESC, $recode);
        if ($isself == 1 && $recode)
        {
            $recode = current($recode);
        }
        return $recode;
    }

    /**
     * 数据库获取用户所有的档案id
     * @param $uid
     * @return array|bool|null
     */
    public function getUserAllRecodeIdFromDms($uid)
    {
        $where = ['uid' => $uid, 'status' => 1];
        try
        {
            $data = $this->where($where)->pluck('id', 'id');
            $data = array_flip_key_value($data);
        }
        catch (Exception $e)
        {
            $this->error = '获取档案失败';
            return false;
        }
        return $data;
    }

    /**
     * 从数据库中获取自己的档案id
     * @param $uid
     * @return bool | array
     */
    public function getSelfRecodeFromDms($uid)
    {
        try
        {
            $data = $this
                ->where(['uid' => $uid, 'isself' => 1, 'status' => 1])
                ->pluck('id', 'id');
            $data = array_flip_key_value($data);
        }
        catch (Exception $e)
        {
            $this->error = '获取档案失败';
            return false;
        }
        return $data;
    }

    /**
     * 数据库批量获取档案信息
     * @param array $ids
     * @return array
     * @throws ApiException
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        $fields = [
        'r.status','r.id','r.name','r.type','r.year','r.month','r.day','r.hour','r.minute','r.timezone','birth_country','birth_province','birth_city','live_country','live_province','live_city','comments','isself','long_deg','long_min','ew','lat_deg','lat_min','ns','avatar','is_summer','or_day','uid','aid','sun','moon','merc','venu','mars','jupi','satu','non','lili','juno','asc','mc','r.is_read'
    ];
        try
        {
            $data = $this->from('recode as r')
                ->join('recode_astro as ra', 'r.aid', '=', 'ra.id')
                ->whereIn('r.id', $ids)
                ->select($fields)
                ->get()
                ->toArray();
        }
        catch (Exception $e)
        {
            throw new ApiException('档案信息获取失败', 200, config('code.error'));
        }
        return $data;
    }

    /**
     * 组成档案日月升信息
     * @param array $recode
     * @return mixed
     */
    public function getRecodeAstroInfo($recode = [])
    {
        $timestamp = strtotime($recode['year'] . '-' . $recode['month'] . '-' . $recode['day'] . ' ' . $recode['hour'] . ':' . $recode['minute']);

        $timestamp -= ($recode['timezone'] + $recode['is_summer']) * 3600;

        $utdatenow = strftime('%d.%m.%Y', $timestamp);
        $utnow = strftime('%H:%M:%S', $timestamp);

        $longitude = ($recode['long_deg'] + $recode['long_min'] / 60) * $recode['ew'];
        $latitude = ($recode['lat_deg'] + $recode['lat_min'] / 60) * $recode['ns'];
        exec(config('astrolog.prefix') . " -b{$utdatenow} -ut{$utnow} -p0123456789DAmHt -eswe -house{$longitude},{$latitude},p -flj -g, -head", $out);

        if (!empty($out) || count($out) < 27)
        {
            unset($out);
            exec(config('astrolog.prefix') . " -b{$utdatenow} -ut{$utnow} -p0123456789DAmHt -eswe -house{$longitude},{$latitude},w -flj -g, -head", $out);
        }
        $planet = $planet_house = [];
        foreach ($out as $k => $line)
        {
            $row = explode(',', $line);

            $planet[$k] = @(float)$row[0];
            $planet_house[$k] = @floor($row[1]);
        }

        $result['sun'] = InWhichSign($planet[0]) . '-' . $planet_house[0] . '-' . $planet[0];
        $result['moon'] = InWhichSign($planet[1]) . '-' . $planet_house[1] . '-' . $planet[1];
        $result['asc'] = InWhichSign($planet[17]) . '-' . $planet_house[17] . '-' . $planet[17];

        return $result;
//        $result['sun'] = InWhichSign($data['p1'][0]).'-'.InWhichHouse($data['p1'][0],$data['hc1']).'-'.$data['p1'][0];
//        $result['moon'] = InWhichSign($data['p1'][1]).'-'.InWhichHouse($data['p1'][1],$data['hc1']).'-'.$data['p1'][1];
//        $result['merc'] = InWhichSign($data['p1'][2]).'-'.InWhichHouse($data['p1'][2],$data['hc1']).'-'.$data['p1'][2];
//        $result['venu'] = InWhichSign($data['p1'][3]).'-'.InWhichHouse($data['p1'][3],$data['hc1']).'-'.$data['p1'][3];
//        $result['mars'] = InWhichSign($data['p1'][4]).'-'.InWhichHouse($data['p1'][4],$data['hc1']).'-'.$data['p1'][4];
//        $result['jupi'] = InWhichSign($data['p1'][5]).'-'.InWhichHouse($data['p1'][5],$data['hc1']).'-'.$data['p1'][5];
//        $result['satu'] = InWhichSign($data['p1'][6]).'-'.InWhichHouse($data['p1'][6],$data['hc1']).'-'.$data['p1'][6];
//        $result['non'] = InWhichSign($data['p1'][12]).'-'.InWhichHouse($data['p1'][12],$data['hc1']).'-'.$data['p1'][12];
//        $result['lili'] = InWhichSign($data['p1'][11]).'-'.InWhichHouse($data['p1'][11],$data['hc1']).'-'.$data['p1'][11];
//        $result['juno'] = InWhichSign($data['p1'][13]).'-'.InWhichHouse($data['p1'][13],$data['hc1']).'-'.$data['p1'][13];
//        $result['asc'] = InWhichSign($data['p1'][17]).'-'.InWhichHouse($data['p1'][17],$data['hc1']).'-'.$data['p1'][17];
//        $result['mc'] = InWhichSign($data['p1'][20]).'-'.InWhichHouse($data['p1'][20],$data['hc1']).'-'.$data['p1'][20];
    }

    /**
     * 检测当前档案是否 有已支付的订单
     * @param array $map
     * id int 档案id
     * uid int 用户id
     * $order_type 1=>校准生辰,2=>日运,3=>月运,4=>年运,5=>幸运之城,6=>教学视频,7=>本命预测
     * @return bool
     * @throws Exception
     */
    public static function checkAboutOrders($map = [])
    {
        $rid = $map['id'];// 档案id
        $uid = $map['uid'];// 用户id
        $ordersCacheModel = new Orders();
        switch (true)
        {
            //检测当前档案是否有校准生辰订单
            case $ordersCacheModel->PrepaidUnpaidOrder($uid, $rid, 1, 1):
                // 检测当前档案是否有日运订单
            case $ordersCacheModel->PrepaidUnpaidOrder($uid, $rid, 2, 1):
                // 检测当前档案是否有月运订单
            case $ordersCacheModel->PrepaidUnpaidOrder($uid, $rid, 3, 1):
                // 检测当前档案是否有年运订单
            case $ordersCacheModel->PrepaidUnpaidOrder($uid, $rid, 4, 1):
                // 检测当前档案是否有幸运之城订单
            case $ordersCacheModel->PrepaidUnpaidOrder($uid, $rid, 5, 1):
                //检测当前档案是否有本命预测订单
            case $ordersCacheModel->PrepaidUnpaidOrder($uid, $rid, 7, 1):
                $res = true;
                break;
            default:
                $res = false;
                break;
        }
        return $res;
    }

    /**
     * 档案添加
     * @param array $data
     * @param string $channel 添加渠道 默认APP WEAPP|QQ|TT
     * @return array
     * @throws ApiException
     */
    public function miniappRecodeAdd(array $data, string $channel = '')
    {
        $recodeInfo = $this->getRecodeInfo($data, $channel);

        $validate = validate('Recode');
        if (!$validate->scene('add')->check($recodeInfo))
        {
            throw new ApiException((string)$validate->getError(), 200, config('code.error'));
        }

        $time = time();
        // 查询当前星盘日月水金火木土等星落座落宫存入数据库
        $astro_data = $this->getAstroData($recodeInfo);

        $rid = $this->SaveData($data['uid'], $recodeInfo);
        if ($rid === false)
        {
            throw new ApiException('服务异常！请稍后再试～', 200, config('code.error'));
        }
        //删除用户缓存
        (new User())->updateUserinfo(['id' => $data['uid']], ['nickname' => $recodeInfo['name'], 'username' => $recodeInfo['name'], 'avatar' => $recodeInfo['avatar'], 'has_self_recode' => 1]);

        $astro_data['rid'] = $rid;
        $astro_data['create_time'] = $time;

        Db::table('recode_info')->insertGetId(['rid' => $rid, 'create_time' => $time, 'last_time' => $time]);// 新增当前档案访问数据

        $aid = Db::table('recode_astro')->insertGetId($astro_data);// 新增当前档案行星数据

        $recodeInfo['id'] = $rid;

        $this->UpdateData($data['uid'], $rid, ['aid' => $aid]);
        // 记录注册日志
        Util::logRealTimeAnalyzeWrite(2, [
            'recode_uid' => $recodeInfo['uid'],
            'recode_rid' => $recodeInfo['id'],
            'recode_sex' => $recodeInfo['type'],//档案类型  1男 | 2 女 | 3 男同 | 4 女同 | 5 事件 | 6 卜卦
            'recode_name' => $recodeInfo['name'],
            'recode_isself' => $recodeInfo['isself'],
            'recode_year' => $recodeInfo['year'],
            'recode_month' => $recodeInfo['month'],
            'recode_day' => $recodeInfo['day'],
            'recode_hour' => $recodeInfo['hour'],
            'recode_minute' => $recodeInfo['minute'],
            'recode_timezone' => $recodeInfo['timezone'],
            'recode_birth_country' => $recodeInfo['birth_country'],
            'recode_birth_province' => $recodeInfo['birth_province'],
            'recode_birth_city' => $recodeInfo['birth_city'],
            'recode_live_country' => $recodeInfo['live_country'],
            'recode_live_province' => $recodeInfo['live_province'],
            'recode_live_city' => $recodeInfo['live_city'],
            'recode_sun' => explode('-', $astro_data['sun'])[0],
            'recode_ip' => request()->ip()
        ]);

        // 记录用户档案更新状态
        $this->setUpdateStatus((int)$data['uid']);

        return $recodeInfo;
    }

    /**
     * 档案添加 或者更新
     * @param string $rid
     * @param array $data
     * @return array
     * @throws ApiException
     */
    public function miniappRecodeAddToCache(string $rid, array $data): array
    {
        $is_summer = 0;
        $noNeedJudgeSummer = ['香港特别行政区', '澳门特别行政区', '台湾省', '北美洲', '大洋洲', '非洲', '南美洲', '欧洲', '亚洲', ''];
        // 只判断大陆地区的夏令时
        if (!in_array($data['birth_country'], $noNeedJudgeSummer, true))
        {
            $is_summer = isSummerTime($data['hour'], $data['minute'], 0, $data['month'], $data['day'], $data['year']) ? 1 : 0;// 是否开启夏令时
        }
        $recodeInfo = [
            'uid' => $data['uid'],
            'name' => $data['name'],
            'type' => $data['type'],
            'year' => $data['year'],
            'month' => $data['month'],
            'day' => $data['day'],
            'hour' => $data['hour'],
            'minute' => $data['minute'],
            'timezone' => 8,
            'birth_country' => $data['birth_country'],
            'birth_province' => $data['birth_province'],
            'birth_city' => $data['birth_city'],
            'live_country' => $data['live_country'],
            'live_province' => $data['live_province'],
            'live_city' => $data['live_city'],
            'comments' => '自己',
            'isself' => 1,
            'long_deg' => $data['long_deg'],
            'long_min' => $data['long_min'],
            'ew' => $data['ew'],
            'lat_deg' => $data['lat_deg'],
            'lat_min' => $data['lat_min'],
            'ns' => $data['ns'],
            'avatar' => $data['avatar'] ?? '',
            'is_summer' => $is_summer,
            'is_read' => 1,//小程序档案默认已读
        ];
        $validate = validate('Recode');

        if (!$validate->scene('add')->check($recodeInfo))
        {
            throw new ApiException((string)$validate->getError(), 200, config('code.error'));
        }

        $Astro = new AstroIndex();
        $longitude = ($data['long_deg'] + $data['long_min'] / 60) * $data['ew'];
        $latitude = ($data['lat_deg'] + $data['lat_min'] / 60) * $data['ns'];
        // 查询当前星盘日月水金火木土等星落座落宫存入数据库
        $astro_data = $Astro->getTheRecodeAstro($data['year'], $data['month'], $data['day'], $data['hour'], $data['minute'], $longitude, $latitude, 8);

        $recodeInfo['astro_info'] = json_encode($astro_data);

        CacheManage::getInstance()->setCacheConfig('miniapp.html_recode', $rid)->setCache($recodeInfo, 'details', false);

        // 删除当前档案今天星座成分缓存
        CacheManage::getInstance()->setCacheConfig('miniapp.total_score', $rid . ':' . date('Ymd'))->rmCache();
        return $recodeInfo;
    }

    public function recodeEdit($rid, $data)
    {
        $recodeInfo = $this->getRecodeInfo($data);

        $recodeInfo['id'] = $rid;

        $validate = validate('Recode');

        if (!$validate->scene('edit')->check($recodeInfo))
        {
            throw new ApiException((string)$validate->getError(), 200, config('code.error'));
        }

        $recode_old = $this->getInfoById($rid);

        // $recodeInfo['isself'] = (int)$recode_old['isself']; // 小程序该字段不更新
        if (!$recodeInfo['avatar'])
        {   // 档案如果为空则不更新
            $recodeInfo['avatar'] = $recode_old['avatar'];
        }

        // 检测档案编辑是否更改时间
        $timeChange = false;// 默认表示时间未进行更新
        $old_time = strtotime($recode_old['year'] . '-' . $recode_old['month'] . '-' . $recode_old['day'] . ' ' . $recode_old['hour'] . ':' . $recode_old['minute']);
        $new_time = strtotime($recodeInfo['year'] . '-' . $recodeInfo['month'] . '-' . $recodeInfo['day'] . ' ' . $recodeInfo['hour'] . ':' . $recodeInfo['minute']);
        // 时间有变动
        if ($old_time != $new_time || $recode_old['timezone'] != $recodeInfo['timezone'] || $recode_old['is_summer'] != $recodeInfo['is_summer'])
        {
            $timeChange = true;

            if (Util::getVips($recodeInfo['uid'], 0, 0))
            {
                $rec = false;
            } // 检测是否存在档案相关已付款订单
            else
            {
                $rec = RecodeCacheModel::checkAboutOrders(['uid' => $recodeInfo['uid'], 'id' => $rid]);
            }

            // 若有，则档案时间只能为当天内变动，若跨日期，则只能在两小时以内变动
            if ($rec === true)
            {
                // 判断or_day是否存在
                if (empty($recode_old['or_day']) || !$recode_old['or_day'])
                {
                    $recode_old['or_day'] = $recode_old['day'];
                    $recodeInfo['or_day'] = $recode_old['day'];
                }

                $limit_time = strtotime($recode_old['year'] . '-' . $recode_old['month'] . '-' . $recode_old['or_day'] . ' 12:00');
                $max = $limit_time + 3600 * 14;
                $min = $limit_time - 3600 * 14;

                if ($new_time > $max || $new_time < $min)
                {
                    throw new ApiException('由于该档案购买过付费项目，修改功能受限，改后时间不能与原档案时间差超过两个小时', 200, config('code.error'));
                }
            }
        }
        // 检测档案编辑是否更改出生地经纬度
        $old_longitude = ($recode_old['long_deg'] + $recode_old['long_min'] / 60) * $recode_old['ew'];
        $old_latitude = ($recode_old['lat_deg'] + $recode_old['lat_min'] / 60) * $recode_old['ns'];
        $new_longitude = ($recodeInfo['long_deg'] + $recodeInfo['long_min'] / 60) * $recodeInfo['ew'];
        $new_latitude = ($recodeInfo['lat_deg'] + $recodeInfo['lat_min'] / 60) * $recodeInfo['ns'];

        $longLatChange = false;

        if ($old_longitude != $new_longitude || $old_latitude != $new_latitude)
        {
            $longLatChange = true;
            $recodeInfo['longitude'] = $new_longitude;
            $recodeInfo['latitude'] = $new_latitude;
        }

//        $Astro = new AstroIndex();
//        // 获取当前数据星盘日月水金火木土等星落座落宫
//        $astro_data = $Astro->getTheRecodeAstro($recodeInfo['year'], $recodeInfo['month'], $recodeInfo['day'], $recodeInfo['hour'], $recodeInfo['minute'], $new_longitude, $new_latitude, $recodeInfo['timezone']);
        //model中不能再鉴权了，所以注释掉上面的内容
        $astro_data = $this->getAstroData($recodeInfo);

        try
        {
            $res = AliyunFilterWord::checkText($recodeInfo['name'], 'username');
            //若内容有违规且超过配置的相似比例，则进行隐藏不显示，将标签存入库中
            if ($res)
            {
                throw new ApiException('昵称涉嫌' . $res['label'] . '，请重新设置', 200, config('code.error'));
            }
            // 更新档案数据
            $recodeInfo = array_merge($recodeInfo, $astro_data);
            $this->UpdateData($recodeInfo['uid'], $rid, $recodeInfo);
            // 如果更新的是自己的档案 且 用户修改了档案名称或头像 则更新用户数据 昵称 头像
            if ($recode_old['isself'] == 1 && ($recodeInfo['name'] != $recode_old['name'] || $recodeInfo['avatar'] != $recode_old['avatar']))
            {
                (new User())->updateUserinfo(['id' => $recodeInfo['uid']], ['nickname' => $recodeInfo['name'], 'avatar' => $recodeInfo['avatar']]);
            }
            // 更新档案行星数据
            if ($timeChange || $longLatChange)
            {
                // 记录用户更新档案的时间
                Db::table('recode_info')->where('rid', $rid)->update(['last_time' => time()]);
                // 更新用户档案档案信息 行星落座信息
                Db::table('recode_astro')->where(['id' => $recode_old['aid']])->update($astro_data);
            }
            $recodeInfo['aid'] = $recode_old['aid'];

            // 档案更新时更新用户档案缓存
            Cache::set('recode_' . $rid, $recodeInfo, 86400 * 7);
            // 档案更新时更新用户档案日月升缓存
            Cache::rm('recode_astro_' . $rid);
            //删除首页用户星座缓存
            Cache::rm('d_f_h_sun_in_sign_' . $rid);

            FortuneCache::rmFortuneDayCache($rid, strtotime(date('Y-m-d') . ' 12:00:00'));
        }
        catch (Exception $e)
        {
            Log::write('编辑档案失败：' . $e->getMessage(), 'edit_recode_error', true);
            throw new ApiException('服务异常，请稍后再试', 200, config('code.error'));
        }
        // 记录用户档案更新状态
        $this->setUpdateStatus($recodeInfo['uid']);
        // 删除当前档案星座成分缓存
        CacheManage::getInstance()->setCacheConfig('miniapp.total_score', $rid . ':' . date('Ymd'))->rmCache();
        return array_merge($recodeInfo, $astro_data);
    }

    /**
     * 设置用户档案更新状态
     * @param int $uid
     * @throws ApiException
     */
    public function setUpdateStatus(int $uid)
    {
        $userInfo = current((new User())->batchGetUserInfo([$uid]));

        if ($userInfo['token'] && time() < $userInfo['token_expire'])
        {   // 如果用户的登陆状态未过期 记录用户档案更新状态
            CacheTools::setRecodeUpdateStatus($uid, 1);
        }
    }

    /**
     * 获取档案信息
     * @param $data
     * @param string $channel
     * @return array
     */
    private function getRecodeInfo($data, $channel = '')
    {
        $is_summer = 0;
        $noNeedJudgeSummer = ['香港特别行政区', '澳门特别行政区', '台湾省', '北美洲', '大洋洲', '非洲', '南美洲', '欧洲', '亚洲', ''];
        // 只判断大陆地区的夏令时
        if (!in_array($data['birth_country'], $noNeedJudgeSummer, true))
        {
            $is_summer = isSummerTime($data['hour'], $data['minute'], 0, $data['month'], $data['day'], $data['year']) ? 1 : 0;// 是否开启夏令时
        }
        $isself = (int)($data['isself'] ?? 1);
        return [
            'uid' => $data['uid'],
            'name' => $data['name'],
            'type' => $data['type'],
            'year' => $data['year'],
            'month' => $data['month'],
            'day' => $data['day'],
            'hour' => $data['hour'],
            'minute' => $data['minute'],
            'timezone' => 8,
            'birth_country' => $data['birth_country'],
            'birth_province' => $data['birth_province'],
            'birth_city' => $data['birth_city'],
            'live_country' => $data['live_country'],
            'live_province' => $data['live_province'],
            'live_city' => $data['live_city'],
            'comments' => (isset($data['comments']) && $data['comments']) ? $data['comments'] : ($isself === 1 ? '自己' : '其他'),
            'isself' => $isself,
            'long_deg' => $data['long_deg'],
            'long_min' => $data['long_min'],
            'ew' => $data['ew'],
            'lat_deg' => $data['lat_deg'],
            'lat_min' => $data['lat_min'],
            'ns' => $data['ns'],
            'avatar' => $data['avatar'] ?? '',
            'is_summer' => $is_summer,
            'channel' => $channel
        ];
    }

    /**
     * 获取星盘数据
     * @param $recodeInfo
     * @return array
     */
    private function getAstroData($recodeInfo)
    {
        $setting = [
            'natal' => [
                'planet' => [
                    [1, 8.5], [1, 7.5], [1, 3.5], [1, 3.5], [1, 4], [1, 4.5], [1, 4.5], [1, 2.5], [1, 2.5], [1, 2.5],
                    [0, 0], [0, 0], [0, 0], [0, 0], [1, 2.5], [0, 0], [0, 0], [1, 2.5], [1, 2.5], [1, 2.5], [1, 2.5]
                ],
                'phase' => [
                    0 => [1, 0], 60 => [1, 0], 90 => [1, 0], 120 => [1, 0], 180 => [1, 0],
                    45 => [0, 0], 135 => [0, 0], 30 => [0, 0], 150 => [0, 0], 72 => [0, 0], 144 => [0, 0]
                ],
                'arabic' => [
                    [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                    [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                    [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
                ],
                'h_sys' => 'p',
                'firdaria' => 'default',
                'bound_type' => 'default',
                'ecliptic' => 0,
                'profection_push_direction' => 0,
                'decanates' => 0,
                'ayanamsa' => 0,
                'location_use' => 0
            ],
        ];
        // 查询当前星盘日月水金火木土等星落座落宫存入数据库
        return Astrolog::getInstance()->setExecPrefix(config('astrolog.prefix'))
            ->setIsAstrolabe(false)
            ->setRecode1($recodeInfo)
            ->setUserSetting($setting)
            ->getTheRecodeAstro();
    }

    /**
     * 组合档案数据
     * @param $recode
     * @return array
     * @throws ApiException
     */
    public function recodeInfoFormat($recode)
    {
        $arr = [
            'isself' => (int)($recode['isself'] ?? 0),
            'avatar' => $recode['avatar'],
            'name' => $recode['name'],
            'recode_time' => $recode['year'] . '.' . sprintf('%02d', $recode['month']) . '.' . sprintf('%02d', $recode['day']) . ' ' . sprintf('%02d', $recode['hour']) . ':' . sprintf('%02d', $recode['minute']),
            'birth_address' => $recode['birth_country'] . $recode['birth_province'] . $recode['birth_city'],
            'live_address' => $recode['live_country'] . $recode['live_province'] . $recode['live_city'],
            'sex' => $recode['type'] == 1 ? '男' : '女'
        ];
        if ($recode['timezone'])
        {
            if ($recode['timezone'] > 0)
            {
                $arr['timezone'] = '东' . (new Util())->numberChinese($recode['timezone']) . '区 GMT+' . $recode['timezone'];
            } else
            {
                $arr['timezone'] = '西' . (new Util())->numberChinese(abs($recode['timezone'])) . '区 GMT' . $recode['timezone'];
            }
        } else
        {
            $arr['timezone'] = '中时区 GMT0';
        }
        if ($recode['birth_country'] && $recode['birth_province'] && $recode['birth_city'])
        {
            $arr['birth_address'] = $recode['birth_country'] . $recode['birth_province'] . $recode['birth_city'];
        }
        if ($recode['ew'] == 1)
        {
            $long = 'E' . $recode['long_deg'] . '°' . $recode['long_min'] . '′';
        } else
        {
            $long = 'W' . $recode['long_deg'] . '°' . $recode['long_min'] . '′';
        }

        if ($recode['ns'] == 1)
        {
            $lat = 'N' . $recode['lat_deg'] . '°' . $recode['lat_min'] . '′';
        } else
        {
            $lat = 'S' . $recode['lat_deg'] . '°' . $recode['lat_min'] . '′';
        }
        $arr['long_lat'] = $long . ' ' . $lat;
        return $arr;
    }

    /**
     * 获取档案信息字符串
     * @param $recode
     * @return string
     */
    public function getRecodeInfoStr($recode)
    {
        return $recode['type'] . $recode['year'] . $recode['month'] . $recode['day'] . $recode['hour'] . $recode['minute'] . $recode['timezone'] . $recode['is_summer'] . $recode['long_deg'] . $recode['long_min'] . $recode['ew'] . $recode['lat_deg'] . $recode['lat_min'] . $recode['ns'];
    }
}
